package com.iuie.ns.system.exception.resolver;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJacksonJsonView;

import com.iuie.ns.frame.exception.ServiceException;
import com.iuie.ns.frame.utils.StringUtils;
import com.iuie.ns.frame.web.response.vo.ResponseInfo;
import com.iuie.ns.system.exception.ApiException;

/**
 * @desc 异常处理类
 * @createTime 2017年8月24日 下午2:26:28
 * @author iuie
 */
public class ExceptionResolver implements HandlerExceptionResolver {
    
    private static final Logger logger = LoggerFactory.getLogger(ExceptionResolver.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
     // 1.过滤掉非API方法
        HandlerMethod method = (HandlerMethod)handler;
        ResponseBody hasResponseBody = method.getMethodAnnotation(ResponseBody.class);
        
        ResponseInfo ri = handle(request, response, handler, ex);
        storeExceptionInfo(ri, ex);
        
        if (hasResponseBody == null) {
            // 返回页面
            ModelAndView mv = new ModelAndView("view-system/error/500");
            mv.addObject("message", ri.getMessage());
            return mv;
        } else {
            // 返回json
            ModelAndView mv = new ModelAndView();
            MappingJacksonJsonView view = new MappingJacksonJsonView();
            mv.setView(view);
            if (ri != null) {
                mv.addAllObjects(ri.toMap(false));
            } else {
                mv.addAllObjects(ResponseInfo.errorInfo("系统错误！").toMap(false));
            }
            return mv;
        }
        
    }

    /**
     * 存储异常信息
     * @param ri
     * @param ex
     * @date 2017年8月24日 下午2:40:57
     */
    private void storeExceptionInfo(ResponseInfo ri, Exception ex) {
        
    }

    /**
     * 异常信息处理
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     * @date 2017年8月24日 下午2:30:10
     */
    private ResponseInfo handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String s = sw.toString();
        
        // 打印异常
        logger.error(s);
        
        if (ex instanceof ServiceException) {
            // service exception
            ServiceException e = (ServiceException) (ex);
            String code = e.getCode();
            Object info = e.getInfo();
            return ResponseInfo.errorInfo(ex.getMessage(), s, code, info);
        } else if (ex instanceof ApiException) {
            // api exception
            ApiException e = (ApiException) ex;
            return ResponseInfo.errorInfo(ex.getMessage(), s, e.getCode(), e.getParams());
        }
        
        String message = ex.getMessage();
        if (StringUtils.isBlank(message)) {
            message = ex.getClass().getName();
        }
        ResponseInfo ri = ResponseInfo.errorInfo(message);
        ri.setExceptionStack(s);
        return ri;
    }
    
    // 从方法上获取apiUrl，apiUrl = method对应类上的requestMapping值 + 
    private String getApiUrl(HandlerMethod method) {
        RequestMapping requestMapping = method.getMethodAnnotation(RequestMapping.class);
        String[] values = requestMapping.value();
        String methodUrl = values[0];
        
        Object bean = method.getBean();
        String controllerUrl = bean.getClass().getAnnotation(RequestMapping.class).value()[0];
        
        String apiUrl = null;
        apiUrl = "/" + controllerUrl + "/" + methodUrl;
        apiUrl = apiUrl.replaceAll("//", "/");
        
        return apiUrl;
    }

}
